package com.zms.maze;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Label;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Map.Entry;
import java.util.NoSuchElementException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.WindowConstants;

import com.zms.maze.MummyConst.Direction;

public class GamePlay extends JFrame implements ActionListener, KeyListener, MouseListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static JFrame frame=new JFrame();
	private static BufferedImage man;
	private static BufferedImage door;
	private static BufferedImage white;
	private static BufferedImage red;
	private static BufferedImage scorpion;
	private static BufferedImage trap;
	private static BufferedImage key;
	private Stroke stroke=new BasicStroke(5f);
	static {
		try {
			man=ImageIO.read(MazeLabel.class.getClassLoader().getResource("man.gif"));
			door=ImageIO.read(MazeLabel.class.getClassLoader().getResource("door.gif"));
			white=ImageIO.read(MazeLabel.class.getClassLoader().getResource("white.gif"));
			red=ImageIO.read(MazeLabel.class.getClassLoader().getResource("red.gif"));
			scorpion=ImageIO.read(MazeLabel.class.getClassLoader().getResource("scorpion.gif"));
			trap=ImageIO.read(MazeLabel.class.getClassLoader().getResource("trap.gif"));
			key=ImageIO.read(MazeLabel.class.getClassLoader().getResource("key.gif"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public PositionManager pm=new PositionManager();
	/**
	 * @param args
	 */
	public GamePlay() {
		super("Maze Creator");
		this.addMouseListener(this);
		this.addKeyListener(this);
		
	}
	
	public static void main(String[] args) {
		GamePlay gp=new GamePlay();
		frame=gp;
		gp.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		gp.setBounds(100,100,500,500);
		gp.setVisible(true);
		gp.loadMaze();
	}
	public void loadMaze()
	{
		paint(getGraphics());
		
	}
	public void paint(Graphics g) {
		if(maze.blockcolumns<1) {
			maze.blockcolumns=10;
		}
		if(maze.blockrows<1) {
			maze.blockrows=10;
		}
		g.setColor(Color.GRAY);
		g.fillRect(0,0,(maze.blockcolumns+2)*Maze.BlockWidth,(maze.blockrows+2)*Maze.BlockHeight);
		g.setColor(Color.DARK_GRAY);
		g.fillRect(Maze.BlockWidth,Maze.BlockHeight,maze.blockcolumns*Maze.BlockWidth,maze.blockrows*Maze.BlockHeight);
		g.setColor(Color.RED);
		for(int i=0;i<=(maze.blockcolumns+2);i++) {
			for(int j=0;j<=(maze.blockrows+2);j++) {
				int x=i*Maze.BlockWidth;
				int y=j*Maze.BlockHeight;
				int r=5;
				g.fillOval(x-r,y-r,2*r,2*r);
			}
		}
		if(maze.explorer.x>=0 && maze.explorer.y>=0) {
			g.drawImage(man,(maze.explorer.x+1)*Maze.BlockWidth+10,(maze.explorer.y+1)*Maze.BlockHeight+10,Maze.BlockWidth-20,Maze.BlockHeight-20,this);
		}
		if(maze.doorx>=-1 && maze.doory>=-1) {
			g.drawImage(door,(maze.doorx+1)*Maze.BlockWidth+10,(maze.doory+1)*Maze.BlockHeight+10,Maze.BlockWidth-20,Maze.BlockHeight-20,this);
		}
		for(Mummy mummy:maze.mummies) {
			BufferedImage image;
			if(mummy.type==MummyType.White) {
				image=white;
			} else {
				image=red;
			}
			g.drawImage(image,(mummy.x+1)*Maze.BlockWidth+10,(mummy.y+1)*Maze.BlockHeight+10,Maze.BlockWidth-20,Maze.BlockHeight-20,this);
		}
//		for(Scorpion ascorpion:maze.scorpions) {
//			g.drawImage(scorpion,(ascorpion.x+1)*Maze.BlockWidth+10,(ascorpion.y+1)*Maze.BlockHeight+10,Maze.BlockWidth-20,Maze.BlockHeight-20,this);
//		}
//		for(Trap atrap:maze.traps) {
//			g.drawImage(trap,(atrap.startx+1)*Maze.BlockWidth+10,(atrap.starty+1)*Maze.BlockHeight+10,Maze.BlockWidth-20,Maze.BlockHeight-20,this);
//		}
		Graphics2D g2d=(Graphics2D)g;
		g2d.setStroke(stroke);
		g2d.setColor(Color.GREEN);
		for(Line line:maze.lines) {			
			g2d.drawLine(Maze.BlockWidth*(line.x1+1),Maze.BlockHeight*(line.y1+1),Maze.BlockWidth*(line.x2+1),Maze.BlockHeight*(line.y2+1));
		}
		if(maze.toggles.size()>0)
		{
			g2d.setColor(Color.PINK);
		}
		for(ToggleLine line:maze.toggles) {
			if (line.state==MummyConst.LOCK)
				g2d.setColor(Color.RED);
			else
				g2d.setColor(Color.WHITE);
			g2d.drawLine(Maze.BlockWidth*(line.x1+1),Maze.BlockHeight*(line.y1+1),Maze.BlockWidth*(line.x2+1),Maze.BlockHeight*(line.y2+1));
			g.drawImage(key,(line.togglex+1)*Maze.BlockWidth+(Maze.BlockWidth-Maze.KeyWidth)/2,(line.toggley+1)*Maze.BlockHeight+(Maze.BlockWidth-Maze.KeyHeight)/2,Maze.BlockWidth-20,Maze.BlockHeight-20,this);
		}
	}
	//Normal:4
	//Simple-56
	//test pre pos: 60
	private Maze maze=getMazeFromFileName("4");
	private Maze initMaze=maze.clone();
	private Maze getMazeFromFile()
	{
		try {
			File parent=new File("C:\\Users\\Phan Quang Trung\\workspace\\MummyMaze\\bin\\data");
			File[] files=parent.listFiles();
			Utilities.getInstance().log(String.valueOf(files.length));
			File file=files[50];
			int n=0;
			System.out.println(++n);
			System.out.println(file);
			ObjectInputStream input=new ObjectInputStream(new FileInputStream(file));
			Maze maze=Maze.readObject(input);
			input.close();				
			ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream(file));
			maze.writeObject(output);
			output.close();
			return maze;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	private Maze getMazeFromFileName(String fileName)
	{
		try {
			File file=new File("C:\\Users\\Phan Quang Trung\\workspace\\MummyMaze\\bin\\data\\"+fileName+".dat");
			int n=0;
			System.out.println(++n);
			System.out.println(file);
			ObjectInputStream input=new ObjectInputStream(new FileInputStream(file));
			Maze maze=Maze.readObject(input);
			input.close();				
			ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream(file));
			maze.writeObject(output);
			output.close();
			return maze;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void keyPressed(KeyEvent e) {
		boolean isValid=false;
		switch (e.getKeyCode()) {
		case KeyEvent.VK_UP:
			if (isValid=maze.canMove(maze.explorer, Direction.UP))
				maze.explorer.moveUp();
			break;
		case KeyEvent.VK_DOWN:
			if (isValid=maze.canMove(maze.explorer, Direction.DOWN))
				maze.explorer.moveDown();
			break;
		case KeyEvent.VK_LEFT:
			if (isValid=maze.canMove(maze.explorer, Direction.LEFT))
				maze.explorer.moveLeft();
			break;
		case KeyEvent.VK_RIGHT:
			if (isValid=maze.canMove(maze.explorer, Direction.RIGHT))
				maze.explorer.moveRight();
			break;
		case KeyEvent.VK_SPACE:
			maze.explorer.stop();
			isValid=true;
			break;
		}
		//After calculate the new position for the explorer, i will assign maze for PositionManager's instance. it will update all maze's attributes depend on the explorer's position.
		//reload the current maze;
		pm.loadMaze(maze);
		//maze=pm.updateMaze();
		String title=maze.getExplorer().getPosString()+maze.mummies.get(0).getPosString();
		super.setTitle(title);
		pm.updateLastState(maze, Direction.WAIT);
		try {
			pm.buildAllState(maze);
			PathFinder solver=new PathFinder(pm.getTransactionBuilder(), pm.getStateTracker().getListWinStates());
			List<String> paths=solver.getDirectionsToRoot(solver.getTreeCollection().get(0),initMaze);
			for(String dir:paths)
			{
				Utilities.getInstance().log(dir);
			}
			//Test get all action
//			Hashtable<Action, Maze> reserveTransaction=transactionBuilder.getTransaction();
//			for( Entry<Action, Maze> entry : reserveTransaction.entrySet() ) {
//				Action temp = entry.getKey();
//			    Maze posMaze = entry.getValue();
//			    String log=String.valueOf(stateNo++)+" "+"["+temp.getMaze().explorer.getPosString()+"-"+temp.getMaze().mummies.get(0).getPosString()+"+"+temp.getDirection().toString()+"]"+"-->"+posMaze.explorer.getPosString()+"-"+posMaze.mummies.get(0).getPosString();
//			    Utilities.getInstance().log(log);
//			}
		} catch (CloneNotSupportedException e1) {
			e1.printStackTrace();
		}
		catch(NoSuchElementException e2)
		{
			e2.printStackTrace();
		}
		if (isValid)
			this.repaint();
	}
	
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		
	}

}

